训练指南 UVA- 11865(有向最小生成树 + 朱刘算法 + 二分) Diposting di 2019-04-24 | Edited on 2019-02-03 Stream My ContestUVA - 11865 二分带宽,然后判断最小生成树是否小于cost值。123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129#include<bits/stdc++.h>using namespace std;typedef long long ll;const ll mod=998244353;const int maxn=100+50;const ll inf=1000000000;;/// 固定根的最小树型图,邻接矩阵写法struct MDST{ int n; int w[maxn][maxn]; ///边权 int vis[maxn]; ///访问标记,仅用来判断无解 int ans; ///计算答案 int removed[maxn]; ///每个点是否被删除 int cid[maxn]; ///所在圈编号 int pre[maxn]; ///最小入边的起点 int iw[maxn]; ///最小入边的权值 int max_cid; ///最大圈编号 void init(int n){ this->n=n; for(int i=0;i<n;i++) for(int j=0;j<n;j++)w[i][j]=inf; } void AddEdge(int u,int v,int cost){ w[u][v]=min(w[u][v],cost); ///重边取权值最小的 } ///从s出发能到达多少个结点 int dfs(int s){ int ans=1; vis[s]=1; for(int i=0;i<n;i++)if(!vis[i]&&w[s][i]<inf)ans+=dfs(i); return ans; } ///从u出发沿着pre指针找圈 bool cycle(int u){ max_cid++; int v=u; while(cid[v]!=max_cid){cid[v]=max_cid;v=pre[v];} return v==u; } /// 计算u的最小入弧,入弧起点不得在圈c中 void update(int u){ iw[u]=inf; for(int i=0;i<n;i++) if(!removed[i]&&w[i][u]<iw[u]){ iw[u]=w[i][u]; pre[u]=i; } } ///根节点为s,如果失败返回false bool solve(int s){ memset(vis,0,sizeof(vis)); if(dfs(s)!=n)return false; memset(removed,0,sizeof(removed)); memset(cid,0,sizeof(cid)); for(int u=0;u<n;u++)update(u); pre[s]=s;iw[s]=0; /// 根结点特殊处理 ans=max_cid=0; for(;;){ bool have_cycle=false; for(int u=0;u<n;u++)if(u!=s&&!removed[u]&&cycle(u)){ have_cycle=true; /// 以下代码缩圈,圈上除了u之外的结点均删除 int v=u; do{ if(v!=u)removed[v]=1; ans+=iw[v]; /// 对于圈外点i,把边i->v改成i->u(并调整权值);v->i改为u->i /// 注意圈上可能还有一个v'使得i->v'或者v'->i存在,因此只保留权值最小的i->u和u->i for(int i=0;i<n;i++)if(cid[i]!=cid[u]&&!removed[i]){ if(w[i][v]<inf)w[i][u]=min(w[i][u],w[i][v]-iw[v]); w[u][i]=min(w[u][i],w[v][i]); if(pre[i]==v)pre[i]=u; } v=pre[v]; }while(v!=u); update(u); break; } if(!have_cycle)break; } for(int i=0;i<n;i++) if(!removed[i])ans+=iw[i]; return true; }};MDST solver;struct Edge{ int u,v,b,c; bool operator <(const Edge& rhs)const{ return b>rhs.b; }};const int maxm=10000+10;int n,m,C;Edge edges[maxm];bool check(int cnt){ solver.init(n); for(int i=0;i<cnt;i++) solver.AddEdge(edges[i].u,edges[i].v,edges[i].c); if(!solver.solve(0))return false; return solver.ans<=C;}int main(){ std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); int t; /* int a=inf; cout<<a<<endl<<1000000000<<endl;*/ cin>>t; while(t--){ cin>>n>>m>>C; for(int i=0;i<m;i++)cin>>edges[i].u>>edges[i].v>>edges[i].b>>edges[i].c; sort(edges,edges+m); int l=1,r=m,ans=-1; while(l<=r){ int mid=(l+r)/2; if(check(mid)){ans=edges[mid-1].b;r=mid-1;} else l=mid+1; } if(ans<0)cout<<"streaming not possible."<<endl; else cout<<ans<<" kbps"<<endl; } return 0;}